package com.mes.inventory.manager;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.mes.common.manager.BasicManager;
import com.mes.common.util.CodeUtil;
import com.mes.common.util.SysUtil;
import com.mes.inventory.dao.InvIODao;
import com.mes.inventory.dao.InvIODetailDao;
import com.mes.inventory.dao.InvInfoDao;
import com.mes.inventory.dao.MaterialDao;
import com.mes.inventory.dao.iface.IInvCheckDao;
import com.mes.inventory.dao.iface.IInvCheckDetailDao;
import com.mes.inventory.domain.InvCheck;
import com.mes.inventory.domain.InvCheckDetail;
import com.mes.inventory.domain.InvIO;
import com.mes.inventory.domain.InvIODetail;
import com.mes.inventory.domain.InvInfo;
import com.mes.inventory.domain.Material;
import com.mes.inventory.manager.iface.IInvInfoManager;
import com.mes.task.dao.iface.IOperationTaskDao;
import com.mes.task.dao.iface.IPartTaskDao;
import com.mes.task.dao.iface.ITaskDao;
import com.mes.task.dao.iface.ITaskPartDao;
import com.mes.task.domain.Task;
import com.mes.task.domain.TaskPart;

@Component
public class InvInfoManager extends BasicManager<InvInfo> implements IInvInfoManager {
	@Autowired
	CodeUtil codeUtil;
	@Autowired
	private InvInfoDao invInfoDao;
	@Autowired
	private MaterialDao materialDao;
	@Autowired
	private InvIODetailDao invIODetailDao;
	@Autowired
	private InvIODao invIODao;
	@Autowired
	private IInvCheckDao invCheckDao;
	@Autowired
	private IInvCheckDetailDao invCheckDetailDao;

	@Autowired
	private ITaskDao taskDao;
	@Autowired
	private IOperationTaskDao operationTaskDao;
	@Autowired
	private IPartTaskDao partTaskDao;
	@Autowired
	private ITaskPartDao taskPartDao;

	@Override
	public void updateInvInfo(List<InvIO> invIOs) throws Exception {
		for (InvIO invIO : invIOs) {
			Set<InvIODetail> details = invIO.getDetails();

			String warehouseUid = invIO.getWarehouseUid();
			if (isOut(invIO)) { // 出库操作
				for (InvIODetail detail : details) {
					InvInfo invInfo = invInfoDao.getInvInfo(detail.getMaterialUid(), invIO.getWarehouseUid(),
							detail.getWarebinUid());
					if (invInfo != null) {
						Float invQty = (float) (invInfo.getInvQty() - detail.getIoQty());
						invInfo.setInvQty(invQty);

						invInfo.setLastInvDate(new Date());
						// invInfo.setTotalAmount(totalAmount);
						// invInfo.setThisTotalAmountOut(thisTotalAmountOut);
						// invInfo.setThisInvQtyOut(thisInvQtyOut);
						// invInfoDao.update(invInfo);
					} else {
						throw new Exception("库存台账中找不到对应的台账记录，请核实。");
					}
				}

				String taskUid = invIO.getTaskUid();
				// 如果是领用出库（领取成品、标准件等用于装配消耗），则更新TaskPart中的实际分配数量
				if (invIO.getIoType() == InvIO.IOTYPE_OUT_USE && taskUid != null) {
					this.updateTaskPart(taskUid, details);
				}
			} else { // 入库操作
				for (InvIODetail detail : details) {
					Material material1 = materialDao.getMaterialByPartUidBatchNumSn(detail.getPartUid(),
							detail.getBatchnum(), detail.getSn());
					if (material1 == null) {
						Material material = new Material();
						material.setUuid(SysUtil.getUUID());
						material.setPartUid(detail.getPartUid());
						material.setPartDrawingId(detail.getPartDrawingId());
						material.setPartName(detail.getPartName());
						material.setPartVersionId(detail.getPartVersionId());
						material.setPartDescription(detail.getPartDescription());
						material.setMaterialType(detail.getMaterialType());
						material.setBatchNum(detail.getBatchnum());
						material.setSn(detail.getSn());
						material.setCheckupDate(new Date());
						material.setMaterialQty(detail.getIoQty());
						materialDao.add(material);
						// detail.setMaterial(material);

						// material1 = material;
						detail.setMaterialUid(material.getUuid());
					} else {
						// 将入库单明细中的materailUid设置值
						material1.setMaterialQty(material1.getMaterialQty() + detail.getIoQty());
						detail.setMaterialUid(material1.getUuid());
					}
					invIODetailDao.update(detail);

					InvInfo invInfo = invInfoDao.getInvInfo(detail.getMaterialUid(), invIO.getWarehouseUid(),
							detail.getWarebinUid());
					if (invInfo != null) {
						Float invQty = (float) (invInfo.getInvQty() + detail.getIoQty());
						invInfo.setInvQty(invQty);
					} else {
						invInfo = new InvInfo();
						invInfo.setUuid(SysUtil.getUUID());
						invInfo.setInvType(InvInfo.INVTYPE_NORMAL);
						invInfo.setMaterialUid(detail.getMaterialUid());
						invInfo.setPartUid(detail.getPartUid());
						invInfo.setPartDrawingId(detail.getPartDrawingId());
						invInfo.setPartName(detail.getPartName());
						invInfo.setPartVersionId(detail.getPartVersionId());
						invInfo.setPartDescription(detail.getPartDescription());
						invInfo.setMaterialType(detail.getMaterialType());
						invInfo.setBatchNum(detail.getBatchnum());
						invInfo.setSn(detail.getSn());

						invInfo.setWarehouseUid(warehouseUid);
						invInfo.setWarebinUid(detail.getWarebinUid());
						if (detail.getIoQty() > 0) {
							invInfo.setInvQty(detail.getIoQty());
						}
						// invInfo.setTotalAmount(totalAmount);
						// invInfo.setThisInvQtyIn(thisInvQtyIn);
						// invInfo.setThisTotalAmountIn(thisTotalAmountIn);
						invInfoDao.add(invInfo);
					}
				}
			}
			// 更新入库单的状态
			invIO.setIoState(5);
			invIODao.update(invIO);
		}

	}

	public static boolean isOut(InvIO invIO) {
		boolean flag = false;

		String iotype = invIO.getIoType() + "";
		if (iotype.charAt(0) == '2') {
			flag = true;
		}

		return flag;
	}

	// 盘点登帐
	@SuppressWarnings("all")
	@Override
	public void updateInvInfoByInvCheck(InvCheck invCheck) throws Exception {
		// 盘亏出库
		// invCheck.setInvCheckType(27);
		InvIO invIO = new InvIO();
		invIO.setUuid(SysUtil.getUUID());
		invIO.setInvIOId(codeUtil.getInvOutBillNumber());
		invIO.setIoState(1);
		// invIO.setIoType(27);
		invIO.setCreatorUid(invCheck.getTransactorUid());
		invIO.setIoDate(new Date());
		invIO.setWarehouseUid(invCheck.getWarehouseUid());
		invIO.setWarehouseUid(invCheck.getWarehouseManagerUid());
		// 盘盈入库
		// invCheck.setInvCheckType(17);
		InvIO invIO1 = new InvIO();
		invIO1.setUuid(SysUtil.getUUID());
		invIO1.setInvIOId(codeUtil.getInvInBillNumber());
		invIO1.setIoState(1);
		invIO1.setIoType(17);
		invIO1.setCreatorUid(invCheck.getTransactorUid());
		invIO1.setIoDate(new Date());
		invIO1.setWarehouseUid(invCheck.getWarehouseUid());
		invIO1.setWarehouseUid(invCheck.getWarehouseManagerUid());

		Set<InvCheckDetail> details = invCheck.getInvCheckDetails();
		for (InvCheckDetail detail : details) {
			Float accountedqty = detail.getAccountedQty();
			Float actualqty = detail.getActualQty();
			// 更新盘点单明细
			detail.setActualQty(actualqty);
			detail.setTolerange(detail.getTolerange());
			detail.setReason(detail.getReason());
			invCheckDetailDao.update(detail);
			if (accountedqty > actualqty) {
				// invIO.setIoType(27);
				InvIODetail invIODetail = new InvIODetail();
				invIODetail.setUuid(SysUtil.getUUID());
				invIODetail.setInvIOUid(invIO.getUuid());
				invIODetail.setPartName(detail.getMaterial().getPartName());
				invIODetail.setPartDescription(detail.getMaterial().getPartName());
				invIODetail.setPartDrawingId(detail.getMaterial().getPartDrawingId());
				invIODetail.setPartUid(detail.getMaterial().getPartUid());
				invIODetail.setWarebinUid(detail.getWarebinUid());
				invIODetail.setIoQty(accountedqty - actualqty);
				invIODetail.setUnitPrice(detail.getUnitPrice());
				invIODetail.setUom(detail.getUom());
				// invIODetail.setAmount((accountedqty-actualqty)*detail.getUnitPrice());
				Set<InvIODetail> set = new HashSet<InvIODetail>();
				set.add(invIODetail);
				invIO.setDetails(set);
				List<InvIO> list = new ArrayList<InvIO>();
				list.add(invIO);
				this.updateInvInfo(list);
			} else if (accountedqty < actualqty) {
				// 盘盈入库
				// invCheck.setInvCheckType(17);
				invIO.setIoType(17);
				InvIODetail invIODetail = new InvIODetail();
				invIODetail.setUuid(SysUtil.getUUID());
				invIODetail.setInvIOUid(invIO.getUuid());
				invIODetail.setPartName(detail.getMaterial().getPartName());
				invIODetail.setPartDescription(detail.getMaterial().getPartName());
				invIODetail.setPartDrawingId(detail.getMaterial().getPartDrawingId());
				invIODetail.setPartUid(detail.getMaterial().getPartUid());
				invIODetail.setWarebinUid(detail.getWarebinUid());
				invIODetail.setIoQty(actualqty - accountedqty);
				invIODetail.setUnitPrice(detail.getUnitPrice());
				invIODetail.setUom(detail.getUom());
				// invIODetail.setAmount((accountedqty-actualqty)*detail.getUnitPrice());
				Set<InvIODetail> set = new HashSet<InvIODetail>();
				set.add(invIODetail);
				invIO1.setDetails(set);
				List<InvIO> list1 = new ArrayList<InvIO>();
				list1.add(invIO1);
				this.updateInvInfo(list1);
			} else {

			}

		}
		// 更新表头状态
		invCheck.setInvCheckState(InvIO.IOSTATE_ACCOUNTED);
		invCheckDao.update(invCheck);
	}

	/**
	 * 领料出库时更新关联任务的TaskPart对象
	 * 
	 * @param taskUid
	 * @param details
	 * @throws Exception
	 */
	public void updateTaskPart(String taskUid, Set<InvIODetail> details) throws Exception {
		Task task = taskDao.getById(taskUid);
		if (task.getTaskType().startsWith("2")) { // 如果关联的是工序任务
//			OperationTask operationTask = operationTaskDao.getById(taskUid);
//			Set<TaskPart> taskParts = operationTask.getTaskParts();
			List<TaskPart> taskParts = taskPartDao.getTaskPartByTaskUid(taskUid);

			if (taskParts == null || taskParts.size() == 0)
				return;

			for (InvIODetail detail : details) {
				float restQty = detail.getIoQty();
				for (TaskPart taskPart : taskParts) {
					if (restQty <= 0)
						continue;

					if (detail.getPartUid().equals(taskPart.getPartUid())) {
						if (taskPart.getAllocatedQty() == null)
							taskPart.setAllocatedQty(0f);

						float reqQty = taskPart.getReqQty() - taskPart.getAllocatedQty();
						if (reqQty > 0) {
							if (restQty > reqQty) {
								taskPart.setAllocatedQty(taskPart.getAllocatedQty() + reqQty);
								restQty = restQty - reqQty;
							} else {
								taskPart.setAllocatedQty(taskPart.getAllocatedQty() + restQty);
								restQty = 0;
							}
							taskPartDao.update(taskPart);
						}
					}
				}
			}
		} else if (task.getTaskType().startsWith("1")) { // 如果关联的是零件任务
//			PartTask partTask = partTaskDao.getById(taskUid);
//			List<OperationTask> operationTasks = partTask.getOperationTasks();
			List<TaskPart> taskParts = taskPartDao.getTaskPartByTaskUid(taskUid);
//			for (OperationTask operationTask : operationTasks) {
//				taskParts.addAll(operationTask.getTaskParts());
//			}

			if (taskParts == null || taskParts.size() == 0)
				return;

			for (InvIODetail detail : details) {
				float restQty = detail.getIoQty();
				for (TaskPart taskPart : taskParts) {
					if (restQty <= 0)
						continue;

					if (detail.getPartUid().equals(taskPart.getPartUid())) {
						if (taskPart.getAllocatedQty() == null)
							taskPart.setAllocatedQty(0f);

						float reqQty = taskPart.getReqQty() - taskPart.getAllocatedQty();
						if (reqQty > 0) {
							if (restQty > reqQty) {
								taskPart.setAllocatedQty(taskPart.getAllocatedQty() + reqQty);
								restQty = restQty - reqQty;
							} else {
								taskPart.setAllocatedQty(taskPart.getAllocatedQty() + restQty);
								restQty = 0;
							}
							taskPartDao.update(taskPart);
						}
					}
				}
			}
		}
	}

}
